#![allow(unused_imports, non_snake_case, non_camel_case_types)]
use super::windows;

mod analysis;
mod defines;
mod factory;
mod factory1;
mod factory2;
mod font;
mod font_collection;
mod font_face;
mod font_fallback;
mod font_family;
mod font_file;
mod strings;

pub use analysis::*;
pub use defines::*;
pub use factory::*;
pub use factory1::*;
pub use factory2::*;
pub use font::*;
pub use font_collection::*;
pub use font_face::*;
pub use font_fallback::*;
pub use font_family::*;
pub use font_file::*;
pub use strings::*;

use windows::*;

pub type IDWriteGeometrySink = IUnknown;
pub type IDWriteRenderingParams = IUnknown;
pub type IDWriteFontFileEnumerator = IUnknown;
pub type IDWriteTextFormat = IUnknown;
pub type IDWriteTextLayout = IUnknown;
pub type IDWriteTypography = IUnknown;
pub type IDWriteGdiInterop = IUnknown;
pub type IDWriteInlineObject = IUnknown;
pub type IDWriteTextAnalyzer = IUnknown;
pub type IDWriteNumberSubstitution = IUnknown;
pub type IDWriteGlyphRunAnalysis = IUnknown;
pub type IDWriteRenderingParams1 = IUnknown;
pub type IDWriteFontFallbackBuilder = IUnknown;
pub type IDWriteColorGlyphRunEnumerator = IUnknown;
pub type IDWriteRenderingParams2 = IUnknown;
pub type IDWriteFontFileStream = IUnknown;
pub type IDWriteFontList = IUnknown;

//
static DWRITE_FACTORY_RAW_PTR: std::sync::OnceLock<usize> = std::sync::OnceLock::new();
#[allow(non_snake_case)]
pub fn DWriteFactory() -> *mut IDWriteFactory {
	let ptr = DWRITE_FACTORY_RAW_PTR.get_or_init(|| unsafe {
		type DWriteCreateFactoryType = extern "system" fn(DWRITE_FACTORY_TYPE, REFIID, *mut *mut IUnknown) -> HRESULT;

		let dwrite_dll = LoadLibraryW("dwrite.dll".to_wide_null().as_ptr());
		if dwrite_dll.is_null() {
			return 0;
		}
		let Ok(create_factory_name) = CString::new("DWriteCreateFactory") else {
			return 0;
		};
		let dwrite_create_factory_ptr = GetProcAddress(dwrite_dll, create_factory_name.as_ptr() as LPCSTR);
		if dwrite_create_factory_ptr.is_null() {
			return 0;
		}
		let dwrite_create_factory = std::mem::transmute::<*const c_void, DWriteCreateFactoryType>(dwrite_create_factory_ptr as *const _);

		let mut factory: *mut IDWriteFactory = ptr::null_mut();
		if S_OK != dwrite_create_factory(DWRITE_FACTORY_TYPE_SHARED, &IDWriteFactory::uuidof(), &mut factory as *mut *mut IDWriteFactory as *mut *mut IUnknown) {
			return 0;
		}
		factory as usize
	});
	(*ptr) as *mut IDWriteFactory
}
